// 文件路径: dbms/ClientHandler.java
package com.dbms;

import com.dbms.common.QueryResult;
import com.dbms.service.Request;
import com.dbms.service.Response;

import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
import java.net.SocketException;

/**
 * 【客户端处理线程】
 *
 * 功能：
 * 1. 负责与单个客户端保持长连接。
 * 2. 负责接收客户端请求（Request 对象）。
 * 3. 调用核心逻辑（DbmsCore）处理请求。
 * 4. 将结果封装为 Response 对象返回给客户端。
 *
 * 特点：
 * - 每个客户端连接由一个独立的线程负责处理。
 * - 使用 Java 序列化对象流（ObjectInputStream / ObjectOutputStream）传递请求和响应。
 * - 支持请求类型：
 *      AUTHENTICATE → 用户认证
 *      EXECUTE_SQL → 执行 SQL 语句
 * - 自动处理客户端断开连接（SocketException）。
 */
public class ClientHandler implements Runnable {
    /** 客户端套接字（每个线程维护一个独立的连接） */
    private final Socket clientSocket;

    /** 数据库管理系统的核心逻辑入口 */
    private final DbmsCore dbmsCore;

    /**
     * 构造方法
     *
     * @param socket 客户端连接的 socket
     * @param core   DBMS 核心逻辑对象
     */
    public ClientHandler(Socket socket, DbmsCore core) {
        this.clientSocket = socket;
        this.dbmsCore = core;
    }

    /**
     * 线程运行方法。
     * - 使用 try-with-resources 自动关闭输入/输出流与 socket。
     * - 持续监听客户端请求，直到客户端主动断开连接。
     */
    @Override
    public void run() {
        try (
                // 输出流：用于将 Response 对象返回给客户端
                ObjectOutputStream oos = new ObjectOutputStream(clientSocket.getOutputStream());
                // 输入流：用于接收客户端发送的 Request 对象
                ObjectInputStream ois = new ObjectInputStream(clientSocket.getInputStream())
        ) {
            // 持续处理客户端请求，直到 socket 关闭
            while (!clientSocket.isClosed()) {
                // =========================================================
                // 1. 读取客户端请求
                // =========================================================
                Request request = (Request) ois.readObject();
                Response response;

                // =========================================================
                // 2. 根据请求类型调用不同逻辑
                // =========================================================
                switch (request.getType()) {
                    case AUTHENTICATE:
                        // 调用核心逻辑执行用户认证
                        boolean authResult = dbmsCore.authenticate(
                                request.getUsername(),
                                request.getPassword()
                        );
                        // 构造响应对象，返回认证结果
                        response = new Response(
                                authResult,
                                "Authentication result.",
                                null, // 认证请求不需要返回 QueryResult
                                dbmsCore.getCurrentUser(),
                                dbmsCore.isInTransaction()
                        );
                        break;

                    case EXECUTE_SQL:
                        // 执行 SQL 语句
                        System.out.println("Executing SQL for " + dbmsCore.getCurrentUser() + ": " + request.getSql());
                        QueryResult queryResult = dbmsCore.processSql(request.getSql());
                        // 将执行结果封装到 Response 中返回
                        response = new Response(
                                queryResult.isSuccess,
                                queryResult.message,
                                queryResult, // 携带完整的执行结果
                                dbmsCore.getCurrentUser(),
                                dbmsCore.isInTransaction()
                        );
                        break;

                    default:
                        // 未知请求类型，返回错误响应
                        QueryResult errorResult = new QueryResult("Unknown request type.");
                        response = new Response(
                                false,
                                errorResult.message,
                                errorResult,
                                dbmsCore.getCurrentUser(),
                                dbmsCore.isInTransaction()
                        );
                        break;
                }

                // =========================================================
                // 3. 将响应发送回客户端
                // =========================================================
                oos.writeObject(response);
                oos.flush(); // 确保数据立即发送
            }
        } catch (SocketException e) {
            // 客户端主动断开连接时触发此异常
            System.out.println("Client " + clientSocket.getInetAddress() + " disconnected.");
        } catch (IOException | ClassNotFoundException e) {
            // 其他异常：IO错误 / 反序列化失败
            System.err.println("Error handling client " + clientSocket.getInetAddress() + ": " + e.getMessage());
            e.printStackTrace();
        }
    }
}
